﻿////
// Extends jQuery with positioning snap-to functions
//

jQuery.fn.extend({

    xsnapDim: function (x, y, h, v) {	// mouse x,y and newly calculated horizontal/vertical center
        var ss = this.data('snaps'), $t, ch, cv;
        var xy = [x, y];

        $t = ss[0][x];
        if ($t) {
            xy[0] = $t.offset().left;
            $('#SNAPLINE0').SnapX(xy[0]);
        } else $('#SNAPLINE0').hide();

        $t = ss[1][x];
        if ($t) {
            xy[0] = $t.offset().left + $t.outerWidth();
            $('#SNAPLINE1').SnapX(xy[0]);
        } else $('#SNAPLINE1').hide();

        //        $t = ss[2][h];
        //        if ($t) {
        //            ch = $t.offset().left + Math.round($t.outerWidth() / 2);
        //            xy[0] = this.offset().left + ((ch - this.offset().left) * 2);
        //            $('#SNAPLINE2').SnapX(ch);
        //        } else $('#SNAPLINE2').hide();

        $t = ss[3][y];
        if ($t) {
            xy[1] = $t.offset().top;
            $('#SNAPLINE3').SnapY(xy[1]);
        } else $('#SNAPLINE3').hide();

        $t = ss[4][y];
        if ($t) {
            xy[1] = $t.offset().top + $t.outerHeight();
            $('#SNAPLINE4').SnapY(xy[1]);
        } else $('#SNAPLINE4').hide();

        //        $t = ss[5][v];
        //        if ($t) {
        //            cv = $t.offset().top + Math.round($t.outerHeight() / 2);
        //            xy[1] = this.offset().top + ((cv - this.offset().top) * 2);
        //            $('#SNAPLINE5').SnapY(cv);
        //        } else $('#SNAPLINE5').hide();

        return xy;
    },

    snapDim: function (x, y, h, v) {	// mouse x,y and newly calculated horizontal/vertical center
        x = Math.round(x);
        y = Math.round(y);
        var wd = h * 2;
        var ht = v * 2;
        var ss = this.data('snaps'), z, ch, cv;
        var xy = [x, y];

        z = ss[0][x];
        if (z) {
            xy[0] = z;
            $('#SNAPLINE0').SnapX(z);
        } else $('#SNAPLINE0').hide();

        z = ss[1][x];
        if (z) {
            xy[0] = z;
            $('#SNAPLINE1').SnapX(z);
        } else $('#SNAPLINE1').hide();

        //        z = ss[2][h];
        //        if (z) {
        //            //ch = z + h;
        //            //xy[0] = this.offset().left + ((ch - this.offset().left) * 2);
        //            xy[0] = z + h;
        //            $('#SNAPLINE2').SnapX(z + h);
        //        } else $('#SNAPLINE2').hide();

        z = ss[3][y];
        if (z) {
            xy[1] = z;
            $('#SNAPLINE3').SnapY(z);
        } else $('#SNAPLINE3').hide();

        z = ss[4][y];
        if (z) {
            xy[1] = z;
            $('#SNAPLINE4').SnapY(z);
        } else $('#SNAPLINE4').hide();

        //        z = ss[5][v];
        //        if (z) {
        //            //cv = $t.offset().top + Math.round($t.outerHeight() / 2);
        //            //xy[1] = this.offset().top + ((cv - this.offset().top) * 2);
        //            xy[1] = z + v;
        //            $('#SNAPLINE5').SnapY(z + v);
        //        } else $('#SNAPLINE5').hide();

        return xy;
    },

    snapPos: function (x, y, w, h) {
        x = Math.round(x);
        y = Math.round(y);
        var ss = this.data('snaps'), v;
        var r = x + w, b = y + h;
        var cx = Math.round((x + r) / 2), cy = Math.round((y + b) / 2);
        var xy = [x, y];

        $('#SNAPLINE0').hide();
        $('#SNAPLINE1').hide();
        $('#SNAPLINE2').hide();
        $('#SNAPLINE3').hide();
        $('#SNAPLINE4').hide();
        $('#SNAPLINE5').hide();

        // Center x
        v = ss[2][cx];
        if (v) {
            xy[0] = Math.round(v - (w / 2));
            $('#SNAPLINE2').SnapX(Math.round(v));
        }

        // Center y
        v = ss[5][cy];
        if (v) {
            xy[1] = Math.round(v - (h / 2));
            $('#SNAPLINE5').SnapY(Math.round(v));
        }

        v = ss[0][x];
        if (v) {
            xy[0] = v;
            $('#SNAPLINE0').SnapX(v);
        }

        v = ss[0][r];
        if (v) {
            xy[0] = v - w;
            $('#SNAPLINE1').SnapX(v);
        }

        v = ss[1][x];
        if (v) {
            xy[0] = v;
            $('#SNAPLINE0').SnapX(v);
        }

        v = ss[1][r];
        if (v) {
            xy[0] = v - w;
            $('#SNAPLINE1').SnapX(v);
        }

        v = ss[3][y];
        if (v) {
            xy[1] = v;
            $('#SNAPLINE3').SnapY(v);
        }

        v = ss[3][b];
        if (v) {
            xy[1] = v - h;
            $('#SNAPLINE4').SnapY(v);
        }

        v = ss[4][y];
        if (v) {
            xy[1] = v;
            $('#SNAPLINE3').SnapY(v);
        }

        v = ss[4][b];
        if (v) {
            xy[1] = v - h;
            $('#SNAPLINE4').SnapY(v);
        }

        return xy;
    },

    snapCollect: function (filter) {
        if (!this.length) return this;
        var $t, p, t, l, r, b, v, h, tilt, wd, ht;
        var st = {};
        var sl = {};
        var sr = {};
        var sb = {};
        var sh = {};
        var sv = {};

        $(filter).each(function () {
            //if (this === el) return;
            $t = $(this);
            wd = $t.outerWidth();
            ht = $t.outerHeight();
            tilt = $t[0].tilt;
            if (tilt) {
                tilt = $t.snapToTilt(Math.abs(tilt));
                wd = $t.snapToTiltW(tilt, wd, ht);
                ht = $t.snapToTiltH(tilt, wd, ht);
            }
            p = $t.offset();
            t = Math.round(p.top);
            l = Math.round(p.left);
            r = Math.round(p.left + wd);
            //if (tilt)
            //    console.log("wd=" + wd + ", left=" + l + ", right=" + r);
            b = Math.round(p.top + ht);
            h = Math.round(p.left + wd / 2);
            v = Math.round(p.top + ht / 2);
            $t.SnapAt(sl, l);
            $t.SnapAt(sr, r);
            $t.SnapAt(st, t);
            $t.SnapAt(sb, b);
            $t.SnapAt(sv, v);
            $t.SnapAt(sh, h);
        });

        this.data('snaps', [sl, sr, sh, st, sb, sv]);
        if ($('#SNAPLINE0').length == 0) {
            $('body').append($('<div/>', { id: 'SNAPLINE0', 'class': 'mojo', css: { position: 'absolute', borderLeft: '1px solid #88F', color: 'transparent', background: 'transparent'} }).html('<b></b>'));
            $('body').append($('<div/>', { id: 'SNAPLINE1', 'class': 'mojo', css: { position: 'absolute', borderLeft: '1px solid #88F', color: 'transparent', background: 'transparent'} }).html('<b></b>'));
            $('body').append($('<div/>', { id: 'SNAPLINE2', 'class': 'mojo', css: { position: 'absolute', borderLeft: '1px solid #8F8', color: 'transparent', background: 'transparent'} }).html('<b></b>'));
            $('body').append($('<div/>', { id: 'SNAPLINE3', 'class': 'mojo', css: { position: 'absolute', borderTop: '1px solid #88F', color: 'transparent', background: 'transparent'} }).html('<b></b>'));
            $('body').append($('<div/>', { id: 'SNAPLINE4', 'class': 'mojo', css: { position: 'absolute', borderTop: '1px solid #88F', color: 'transparent', background: 'transparent'} }).html('<b></b>'));
            $('body').append($('<div/>', { id: 'SNAPLINE5', 'class': 'mojo', css: { position: 'absolute', borderTop: '1px solid #8F8', color: 'transparent', background: 'transparent'} }).html('<b></b>'));
        }
        return this;
    },

    snapDump: function () {
        if (!this.length) return this;
        $('#SNAPLINE0').hide();
        $('#SNAPLINE1').hide();
        $('#SNAPLINE2').hide();
        $('#SNAPLINE3').hide();
        $('#SNAPLINE4').hide();
        $('#SNAPLINE5').hide();
        this.removeData('snaps');
        return this;
    },

    SnapAt: function (g, s) {
        //return g[s - 2] = g[s - 1] = g[s] = g[s + 1] = g[s + 2] = s; // 2px snap
        return g[s - 3] = g[s - 2] = g[s - 1] = g[s] = g[s + 1] = g[s + 2] = g[s + 3] = s; // 3px snap
    },

    SnapX: function (x) {
        return this.css({ top: 0 + $(window).scrollTop(), left: x + $(window).scrollLeft(), width: 0, height: $(window).height() - 1 }).show();
    },

    SnapY: function (y) {
        return this.css({ top: y + $(window).scrollTop(), left: 0 + $(window).scrollLeft(), width: $(window).width() - 1, height: 0 }).show();
    },

    snapToTilt: function (tilt) {
        if (tilt > 270) tilt = 360 - tilt;
        else if (tilt > 180) tilt = tilt - 180;
        else if (tilt > 90) tilt = 180 - tilt;
        return tilt * Math.PI / 180; // Convert to radians
    },

    snapToTiltW: function (tilt, w, h) {
        return Math.round(Math.abs(w * Math.cos(tilt)) + Math.abs(h * Math.sin(tilt)));
    },

    snapToTiltH: function (tilt, w, h) {
        return Math.round(Math.abs(w * Math.sin(tilt)) + Math.abs(h * Math.cos(tilt)));
    }
});
